/*************************************************
filename	: graphics_module.h
author		: Stefan lulham
desc		: Contains the base graphics module
*************************************************/
#ifndef D_GRAPHICS_H
#define D_GRAPHICS_H

#include <string>

#include <platform.h>
#include <modules\module.h>

#include <modules\system\system_module.h>

#include <modules\graphics\graphics_interface.h>
#include <modules\graphics\opengl\opengl_graphics_interface.h>
#if defined(DELGE_PLATFORM_WIN32)
//#include <modules\graphics\direct3d9\d3d9_graphics_interface.h>
#endif

#include <modules\graphics\color.h>
#include <modules\graphics\vertex.h>
#include <modules\graphics\indexed_triangle.h>
#include <modules\graphics\mesh.h>
#include <modules\graphics\texture.h>
#include <modules\graphics\sprite.h>
#include <modules\graphics\camera.h>
#include <modules\graphics\font.h>
#include <modules\graphics\model.h>
#include <modules\graphics\entity_pose.h>
#include <modules\graphics\static_entity.h>
#include <modules\graphics\animated_entity.h>
#include <modules\graphics\transformable.h>
#include <modules\graphics\graphics_context.h>
#include <modules\graphics\graphics_enums.h>
#include <modules\graphics\md2_entity_loader.h>

#undef DrawText

using namespace std;
using namespace DelGE::Modules::System;

namespace DelGE
{
	namespace Modules
	{
		namespace Graphics
		{
			class GraphicsModule : public Module
			{
			private:
				OpenGLGraphicsInterface* pOpenGL_GraphicsInterface;
				#if defined(DELGE_PLATFORM_WIN32)
				//D3D9GraphicsInterface* pD3D9_GraphicsInterface;
				#endif

			protected:
				void LoadModule();
				void UnloadModule();

			public:
				GraphicsModule();
				~GraphicsModule();

				OpenGLGraphicsInterface* GetInterface_OpenGL();
				#if defined(DELGE_PLATFORM_WIN32)
				//D3D9GraphicsInterface* GetInterface_D3D9();
				#endif

				void SetCurrentContext(GraphicsContext* pContext);
				GraphicsContext* GetCurrentContext();
				GraphicsContext* CreateContext(SystemGadget* pGadget);
				#if defined(DELGE_PLATFORM_WIN32)
				GraphicsContext* CreateContext(HWND hWnd);
				#endif
				void DestroyAllContexts();

				void Setup2DProjection(int iWidth = -1, int iHeight = -1);
				void SetViewport(int iX, int iY, int iWidth, int iHeight);

				void SetClearColor(int iRed, int iGreen, int iBlue, int iAlpha = 255);
				void SetClearColor(const Color& rColor);
				int GetClearColor_Red();
				int GetClearColor_Green();
				int GetClearColor_Blue();
				int GetClearColor_Alpha();
				Color GetClearColor();

				void SetGlobalColor(int iRed, int iGreen, int iBlue, int iAlpha = 255);
				void SetGlobalColor(const Color& rColor);
				int GetGlobalColor_Red();
				int GetGlobalColor_Green();
				int GetGlobalColor_Blue();
				int GetGlobalColor_Alpha();
				Color GetGlobalColor();

				void ClearScreen();
				void Flip();
				void SetVsync(bool bVsync);

				void SetBlendMode(DelGEGraphicsBlendMode eBlendMode);
				DelGEGraphicsBlendMode GetBlendMode();

				Texture* LoadTexture(string sFilepath, 
											 const Color& oMaskColor = DELGE_GRAPHICSCOLOR_NONE, 
											 GraphicsTexture_UVWrapMode eUWrapMode = GraphicsTexture_UVWrapMode_Clamp,
											 GraphicsTexture_UVWrapMode eVWrapMode = GraphicsTexture_UVWrapMode_Clamp);
				Texture* CreateTexture(int iWidth, int iHeight,
											   GraphicsTexture_UVWrapMode eUWrapMode = GraphicsTexture_UVWrapMode_Clamp,
											   GraphicsTexture_UVWrapMode eVWrapMode = GraphicsTexture_UVWrapMode_Clamp);
				void UnloadTexture(Texture* pGraphicsTexture);

				Font* LoadFont(string sFilepath, int iSize);
				void UnloadFont(Font* pFont);

				void BeginRenderToTexture(Texture* pGraphicsTexture);
				void EndRenderToTexture();

				void DrawRect(float fX, float fY, float fWidth, float fHeight);
				void DrawLine(float fX0, float fY0, float fX1, float fY1);
				void DrawTexture(Texture* pTexture, float fX, float fY, float fWidth = -1, float fHeight = -1);
				void DrawTextureArea(Texture* pTexture, float fX, float fY, float fWidth = -1, float fHeight = -1,
									 int iAreaX = -1, int iAreaY = -1, int iAreaWidth = -1, int iAreaHeight = -1);
				void DrawMesh(Mesh* pMesh, bool bAutoBuild = true);
				void DrawModel(Model* pModel);
				void DrawEntity(Entity* pEntity);
				void DrawCamera(Camera* pCamera);
				void DrawSprite(Sprite* pSprite);
				void DrawText(string sText, float fX, float fY, Font* pFont);

				void BindTexture(Texture* pTexture);

				float TextWidth(string sText, Font* pFont);
				float TextHeight(string sText, Font* pFont);

				void SetModelViewMatrix(const Matrix& rMatrix);
				void SetProjectionMatrix(const Matrix& rMatrix);
				Matrix GetModelViewMatrix();
				Matrix GetProjectionMatrix();

				void PushWorldMatrix();
				void PopWorldMatrix();

				void Begin2DRendering();
				void Begin3DRendering();

				void EnableWireframeMode();
				void EnableDepthTesting();
				void DisableWireframeMode();
				void DisableDepthTesting();

				void EnableLighting();
				void DisableLighting();
			};
		}
	}
}

#endif